package com.carol.lmsbe.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.carol.lmsbe.dto.ConsumableItemCreateRequest;
import com.carol.lmsbe.dto.ConsumablePlanCreateRequest;
import com.carol.lmsbe.dto.ConsumablePlanDTO;
import com.carol.lmsbe.dto.ConsumablePlanQueryRequest;
import com.carol.lmsbe.entity.ConsumableItem;
import com.carol.lmsbe.entity.ConsumablePlan;
import com.carol.lmsbe.entity.Laboratory;
import com.carol.lmsbe.entity.User;
import com.carol.lmsbe.mapper.ConsumableItemMapper;
import com.carol.lmsbe.mapper.ConsumablePlanMapper;
import com.carol.lmsbe.mapper.LaboratoryMapper;
import com.carol.lmsbe.mapper.UserMapper;
import com.carol.lmsbe.service.ConsumablePlanService;
import com.carol.lmsbe.security.JwtAuthenticationFilter;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 易耗品计划服务实现类
 */
@Service
public class ConsumablePlanServiceImpl implements ConsumablePlanService {

    @Autowired
    private ConsumablePlanMapper consumablePlanMapper;

    @Autowired
    private ConsumableItemMapper consumableItemMapper;

    @Autowired
    private LaboratoryMapper laboratoryMapper;

    @Autowired
    private UserMapper userMapper;

    @Override
    public Page<ConsumablePlanDTO> listPlans(ConsumablePlanQueryRequest request) {
        Page<ConsumablePlan> page = new Page<>(request.getCurrent(), request.getSize());
        
        LambdaQueryWrapper<ConsumablePlan> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(request.getSemester() != null && !request.getSemester().trim().isEmpty(), ConsumablePlan::getSemester, request.getSemester())
                   .eq(request.getLaboratoryId() != null && request.getLaboratoryId() > 0, ConsumablePlan::getLaboratoryId, request.getLaboratoryId())
                   .eq(request.getStatus() != null && !request.getStatus().trim().isEmpty(), ConsumablePlan::getStatus, request.getStatus())
                   .orderByDesc(ConsumablePlan::getCreateTime);

        Page<ConsumablePlan> planPage = consumablePlanMapper.selectPage(page, queryWrapper);
        
        Page<ConsumablePlanDTO> dtoPage = new Page<>(planPage.getCurrent(), planPage.getSize(), planPage.getTotal());
        List<ConsumablePlanDTO> dtoList = planPage.getRecords().stream().map(this::convertToDTO).collect(Collectors.toList());
        dtoPage.setRecords(dtoList);
        
        return dtoPage;
    }

    @Override
    public ConsumablePlanDTO getPlanById(Long id) {
        ConsumablePlan plan = consumablePlanMapper.selectById(id);
        if (plan == null) {
            throw new RuntimeException("易耗品计划不存在");
        }
        
        ConsumablePlanDTO dto = convertToDTO(plan);
        
        // 获取计划明细
        LambdaQueryWrapper<ConsumableItem> itemWrapper = new LambdaQueryWrapper<>();
        itemWrapper.eq(ConsumableItem::getPlanId, id);
        List<ConsumableItem> items = consumableItemMapper.selectList(itemWrapper);
        dto.setItems(items.stream().map(this::convertItemToDTO).collect(Collectors.toList()));
        
        return dto;
    }

    @Override
    @Transactional
    public ConsumablePlanDTO createPlan(ConsumablePlanCreateRequest request) {
        // 获取当前用户
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Long currentUserId = getCurrentUserId(authentication);
        
        // 创建计划
        ConsumablePlan plan = new ConsumablePlan();
        plan.setSemester(request.getSemester());
        plan.setLaboratoryId(request.getLaboratoryId());
        plan.setApplicantId(currentUserId);
        plan.setStatus("DRAFT");
        
        // 计算总金额
        BigDecimal totalAmount = request.getItems().stream()
                .map(item -> item.getUnitPrice().multiply(BigDecimal.valueOf(item.getPlannedQuantity())))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        plan.setTotalBudget(totalAmount.doubleValue());
        
        consumablePlanMapper.insert(plan);
        
        // 创建计划明细
        for (ConsumableItemCreateRequest itemRequest : request.getItems()) {
            ConsumableItem item = new ConsumableItem();
            item.setPlanId(plan.getId());
            item.setName(itemRequest.getName());
            item.setSpecification(itemRequest.getSpecification());
            item.setUnit(itemRequest.getUnit());
            item.setPlannedQuantity(itemRequest.getPlannedQuantity());
            item.setUnitPrice(itemRequest.getUnitPrice());
            item.setTotalAmount(itemRequest.getUnitPrice().multiply(BigDecimal.valueOf(itemRequest.getPlannedQuantity())));
            item.setActualQuantity(0);
            
            consumableItemMapper.insert(item);
        }
        
        return getPlanById(plan.getId());
    }

    @Override
    @Transactional
    public ConsumablePlanDTO updatePlan(Long id, ConsumablePlanCreateRequest request) {
        ConsumablePlan plan = consumablePlanMapper.selectById(id);
        if (plan == null) {
            throw new RuntimeException("易耗品计划不存在");
        }
        
        if (!"DRAFT".equals(plan.getStatus())) {
            throw new RuntimeException("只有草稿状态的计划可以修改");
        }
        
        // 更新计划基本信息
        plan.setSemester(request.getSemester());
        plan.setLaboratoryId(request.getLaboratoryId());
        
        // 计算总金额
        BigDecimal totalAmount = request.getItems().stream()
                .map(item -> item.getUnitPrice().multiply(BigDecimal.valueOf(item.getPlannedQuantity())))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        plan.setTotalBudget(totalAmount.doubleValue());
        
        consumablePlanMapper.updateById(plan);
        
        // 删除原有明细
        LambdaQueryWrapper<ConsumableItem> deleteWrapper = new LambdaQueryWrapper<>();
        deleteWrapper.eq(ConsumableItem::getPlanId, id);
        consumableItemMapper.delete(deleteWrapper);
        
        // 创建新的明细
        for (ConsumableItemCreateRequest itemRequest : request.getItems()) {
            ConsumableItem item = new ConsumableItem();
            item.setPlanId(plan.getId());
            item.setName(itemRequest.getName());
            item.setSpecification(itemRequest.getSpecification());
            item.setUnit(itemRequest.getUnit());
            item.setPlannedQuantity(itemRequest.getPlannedQuantity());
            item.setUnitPrice(itemRequest.getUnitPrice());
            item.setTotalAmount(itemRequest.getUnitPrice().multiply(BigDecimal.valueOf(itemRequest.getPlannedQuantity())));
            item.setActualQuantity(0);
            
            consumableItemMapper.insert(item);
        }
        
        return getPlanById(plan.getId());
    }

    @Override
    public void deletePlan(Long id) {
        ConsumablePlan plan = consumablePlanMapper.selectById(id);
        if (plan == null) {
            throw new RuntimeException("易耗品计划不存在");
        }
        
        if (!"DRAFT".equals(plan.getStatus())) {
            throw new RuntimeException("只有草稿状态的计划可以删除");
        }
        
        // 删除计划明细
        LambdaQueryWrapper<ConsumableItem> deleteWrapper = new LambdaQueryWrapper<>();
        deleteWrapper.eq(ConsumableItem::getPlanId, id);
        consumableItemMapper.delete(deleteWrapper);
        
        // 删除计划
        consumablePlanMapper.deleteById(id);
    }

    @Override
    public void submitPlan(Long id) {
        ConsumablePlan plan = consumablePlanMapper.selectById(id);
        if (plan == null) {
            throw new RuntimeException("易耗品计划不存在");
        }
        
        if (!"DRAFT".equals(plan.getStatus())) {
            throw new RuntimeException("只有草稿状态的计划可以提交");
        }
        
        plan.setStatus("SUBMITTED");
        consumablePlanMapper.updateById(plan);
    }

    @Override
    public void approvePlan(Long id, String status, String comment) {
        ConsumablePlan plan = consumablePlanMapper.selectById(id);
        if (plan == null) {
            throw new RuntimeException("易耗品计划不存在");
        }
        
        if (!"SUBMITTED".equals(plan.getStatus())) {
            throw new RuntimeException("只有已提交状态的计划可以审批");
        }
        
        // 获取当前用户
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Long currentUserId = getCurrentUserId(authentication);
        
        plan.setStatus(status);
        plan.setApproverId(currentUserId);
        plan.setApprovalTime(LocalDateTime.now());
        plan.setApprovalComment(comment);
        
        consumablePlanMapper.updateById(plan);
    }

    @Override
    public Page<ConsumablePlanDTO> getMyPlans(ConsumablePlanQueryRequest request) {
        // 获取当前用户
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Long currentUserId = getCurrentUserId(authentication);
        
        // 根据用户角色过滤
        User user = userMapper.selectById(currentUserId);
        if ("LAB_MANAGER".equals(user.getRole())) {
            request.setLaboratoryId(user.getLaboratoryId());
        }
        
        return listPlans(request);
    }

    private ConsumablePlanDTO convertToDTO(ConsumablePlan plan) {
        ConsumablePlanDTO dto = new ConsumablePlanDTO();
        BeanUtils.copyProperties(plan, dto);
        
        // 设置实验室名称
        if (plan.getLaboratoryId() != null) {
            Laboratory laboratory = laboratoryMapper.selectById(plan.getLaboratoryId());
            if (laboratory != null) {
                dto.setLaboratoryName(laboratory.getName());
            }
        }
        
        // 设置申请人名称
        if (plan.getApplicantId() != null) {
            User applicant = userMapper.selectById(plan.getApplicantId());
            if (applicant != null) {
                dto.setApplicantName(applicant.getRealName());
            }
        }
        
        // 设置审批人名称
        if (plan.getApproverId() != null) {
            User approver = userMapper.selectById(plan.getApproverId());
            if (approver != null) {
                dto.setApproverName(approver.getRealName());
            }
        }
        
        return dto;
    }

    private com.carol.lmsbe.dto.ConsumableItemDTO convertItemToDTO(ConsumableItem item) {
        com.carol.lmsbe.dto.ConsumableItemDTO dto = new com.carol.lmsbe.dto.ConsumableItemDTO();
        BeanUtils.copyProperties(item, dto);
        return dto;
    }

    /**
     * 获取当前用户ID
     */
    private Long getCurrentUserId(Authentication authentication) {
        if (authentication == null || authentication.getPrincipal() == null) {
            throw new RuntimeException("用户未登录");
        }
        
        Object principal = authentication.getPrincipal();
        if (principal instanceof com.carol.lmsbe.security.JwtAuthenticationFilter.UserPrincipal) {
            return ((com.carol.lmsbe.security.JwtAuthenticationFilter.UserPrincipal) principal).getUserId();
        } else if (principal instanceof String) {
            // 如果principal是用户名，则通过用户名查找用户ID
            User user = userMapper.selectOne(new LambdaQueryWrapper<User>()
                    .eq(User::getUsername, principal));
            if (user == null) {
                throw new RuntimeException("用户不存在");
            }
            return user.getId();
        } else {
            throw new RuntimeException("无法获取用户信息");
        }
    }
}
